﻿#ifndef XVARIANT_TOOL_HPP
#define XVARIANT_TOOL_HPP
#include <lpb_reflect/library/xtypelist.hpp>
#include <lpb_reflect/library/xvaluelist.hpp>

namespace NS_variant{
	template<typename T>
	struct getMemberType;

	template<typename class_type,typename member_type>
	struct getMemberType<member_type class_type::*> {
		using class_t = class_type;
		using member_t = member_type;
	};

	template<typename T>
	struct getFunparameters;

	template<typename objT, typename ret, typename ...Args>
	struct getFunparameters< ret(objT::*)(Args...)> {
		using class_t = objT;
		using ret_t = ret;
		using parameter_list_t = TL::typelsit<Args...>;
		static constexpr int num = sizeof...(Args);
	};

	template<typename ret, typename ...Args>
	struct getFunparameters< ret(*)(Args...)> {
		using ret_t = ret;
		using parameter_list_t = TL::typelsit<Args...>;
		static constexpr int num = sizeof...(Args);
	};

	template<typename T>
	struct convert_ref {
		using type = T;
	};

	template<typename T>
	struct convert_ref<T &> {
		using type = std::reference_wrapper<T>;
	};

	template<typename T>
	struct convert_ref<const T&> {
		using type = T;
	};

	template<typename T>
	using convert_ref_t = typename convert_ref<T>::type;
}


namespace NS_variant{
//获取某个元素的可转换的元素的序列
    template<typename Tlist_All,typename TList,typename T,bool  = TL::TL_isEqual_v<TL::TL_sizeof_v<TList>, 1>>
    struct TL_getConvertSeq;

    template<typename VList,typename VList::type element,bool flag = true>
    struct if_insert{
        using type = VL::VL_pushBack_t<VList,element>;
    };

    template<typename VList,typename VList::type element>
    struct if_insert<VList,element,false>{
        using type = VList;
    };

    template<typename Tlist_All, typename TList,typename T>
    struct TL_getConvertSeq<Tlist_All,TList,T,false>{
        using head = TL::TL_Front_t<TList>;
        using tail = typename TL_getConvertSeq<Tlist_All,TL::TL_PopFront_t<TList>,T>::type;
        static constexpr bool flag = std::is_convertible_v<head,T>;
        using type = typename if_insert<tail,TL::TL_indexOf_v<Tlist_All,head>,flag>::type;
    };

     template<typename Tlist_All,typename TList,typename T>
    struct TL_getConvertSeq<Tlist_All,TList,T,true>{
        using head = TL::TL_Front_t<TList>;
        using type = typename if_insert<VL::valuelist<unsigned int>,TL::TL_indexOf_v<Tlist_All,head>,std::is_convertible_v<head,T>>::type;
    };

    template<typename Tlist_All,typename TList,typename T,bool  = TL::TL_isEqual_v<TL::TL_sizeof_v<TList>, 1>>
    using  TL_getConvertSeq_T = typename TL_getConvertSeq<Tlist_All,TList,T>::type;

	template<typename VList>
	struct isContainer;

	template<unsigned int N1,unsigned int ... seqs>
	struct isContainer<VL::valuelist<unsigned int,N1,seqs...>>{
		static constexpr bool isContainerImpl(unsigned int index){
			if(N1 ==index){
				return true;
			}else{
				return isContainer<VL::valuelist<unsigned int,seqs...>>::isContainerImpl(index);
			}
		}
	};

	template<unsigned int N1>
	struct isContainer<VL::valuelist<unsigned int,N1>>{
		static constexpr bool isContainerImpl(unsigned int index){
			return (N1 ==index);
		}
	};
}
#endif